#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
@author:Zx
@file: app_run.py
@time: 2025/7/23  10:47
# @describe: 主应用文件(新)
"""
from datetime import datetime, timedelta, date
from pathlib import Path
import json
from flask import Flask, render_template, jsonify
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
from config import Config
from models import announcement
from utils.logging_utils import configure_logging
from utils.auth_utils import init_login_manager
from utils.data_utils import init_stats_file, init_user_file, record_blocked_ip
from routes import auth, hikes, comments, profile, messages, announcements
import logging
import os
from models.announcement import announcement_manager


# 创建应用实例
app = Flask(__name__)
app.config.from_object(Config)

# 初始化 AnnouncementManager
announcement_manager.init_app(app)

# 配置日志
configure_logging(app)
logger = logging.getLogger(__name__)

# 确保data目录存在
DATA_DIR = Path(__file__).parent / 'data'
DATA_DIR.mkdir(exist_ok=True)

# 初始化登录管理器
login_manager = init_login_manager(app)

# 初始化数据文件
init_stats_file()
init_user_file()

# 配置限流器
limiter = Limiter(
    app=app,
    key_func=get_remote_address,
    default_limits=["200 per minute", "50 per 10 seconds"],
    storage_uri="memory://",
    on_breach=record_blocked_ip
)


def init_announcements_file():
    """初始化公告数据文件"""
    announcements_file = DATA_DIR / 'announcements.json'
    try:
        if not announcements_file.exists():
            with open(announcements_file, 'w', encoding='utf-8') as f:
                json.dump([], f, ensure_ascii=False, indent=2)
            logger.info("公告数据文件初始化成功")
    except Exception as e:
        logger.error(f"初始化公告数据文件失败: {str(e)}")
        raise


def init_hikes_file():
    """初始化徒步路线数据文件"""
    hikes_file = DATA_DIR / 'hikes.json'
    try:
        if not hikes_file.exists():
            with open(hikes_file, 'w', encoding='utf-8') as f:
                json.dump([], f, ensure_ascii=False, indent=2)
            logger.info("徒步路线数据文件初始化成功")
    except Exception as e:
        logger.error(f"初始化徒步路线数据文件失败: {str(e)}")
        raise


def init_data_files():
    """初始化所有JSON数据文件"""
    try:
        init_announcements_file()
        init_hikes_file()
        # 可以继续添加其他需要初始化的数据文件
        logger.info("所有数据文件初始化完成")
    except Exception as e:
        logger.critical(f"数据文件初始化失败: {str(e)}")
        raise


# 应用启动时初始化数据文件
with app.app_context():
    init_data_files()


# 自定义限流错误处理
@app.errorhandler(429)
def ratelimit_handler(e):
    try:
        ip = get_remote_address() or "unknown"
        record_blocked_ip(ip)
    except Exception as e:
        logger.error(f"限流处理失败: {e}")

    return jsonify({
        "error": "rate_limit_exceeded",
        "message": "请求过于频繁，请稍后再试",
        "detail": str(e.description),
        "client_ip": ip
    }), 429


# 注册蓝图
app.register_blueprint(auth.auth_bp, url_prefix='')
app.register_blueprint(hikes.hikes_bp, url_prefix='')
app.register_blueprint(comments.comments_bp, url_prefix='')
app.register_blueprint(profile.profile_bp, url_prefix='')
app.register_blueprint(messages.messages_bp, url_prefix='')
app.register_blueprint(announcements.announcement_bp, url_prefix='')


# 注册模板过滤器
@app.template_filter('number_format')
def number_format(value):
    try:
        value = int(value)
        if value >= 10000:
            return f"{value / 10000:.1f}w"
        elif value >= 1000:
            return f"{value / 1000:.1f}k"
        return str(value)
    except:
        return str(value)


@app.template_filter('datetimeformat')
def datetimeformat(value, format='%Y-%m-%d %H:%M'):
    try:
        if isinstance(value, str):
            value = datetime.fromisoformat(value)
        return value.strftime(format)
    except (ValueError, AttributeError) as e:
        logger.error(f"日期格式转换失败: {e}, 原始值: {value}")
        return str(value)


# 错误处理
@app.errorhandler(404)
def page_not_found(e):
    return render_template('error.html',
                           message="页面未找到",
                           error_code="404",
                           now=datetime.now()), 404


@app.errorhandler(500)
def internal_server_error(e):
    print(datetime.now())
    return render_template('error.html',
                           message='服务器内部错误',
                           error_code="500",
                           now=datetime.now()), 500


if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5001, debug=True)